package com.families.shiro;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import com.families.dao.LoginDao;
import com.families.dao.UserMapper;
import com.families.entity.User;

//AuthenticatingRealm只支持认证
//AuthorizingRealm支持认证和授权
public class MyRealm extends AuthenticatingRealm{
	 
    @Autowired
    private UserMapper userMapper;
    @Autowired
    SessionDAO sessionDAO;
    @Autowired
    RedisTemplate<String,String> redisTemplate;
    @Value("${error.timeout}")
    private Integer timeout;
    @Value("${lock.timeout}")
    private Integer locktimeout;
    
	private static final Logger logger = LoggerFactory.getLogger(MyRealm.class);

	
    //认证方法
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		// TODO Auto-generated method stub
		System.out.println("身份认证方法：MyShiroRealm.doGetAuthenticationInfo()");
		
		//牵制转换成usernamepasswordtoken
		UsernamePasswordToken uToken=(UsernamePasswordToken) token;
		//获取用户名
		String username=uToken.getUsername();
		//访问一次，计数一次
		ValueOperations<String,String> opsForValue = redisTemplate.opsForValue();
		if("Lock".equals(opsForValue.get("SHIRO_IS_LOCK"+username))) {
			opsForValue.set("SHIRO_LOGIN_COUNT"+username, "0");
			throw new DisabledAccountException("由于密码连续输错"+timeout+"次,账户锁定1分钟");
		}
		opsForValue.increment("SHIRO_LOGIN_COUNT"+username,1);
		if(Integer.parseInt(opsForValue.get("SHIRO_LOGIN_COUNT"+username))>=timeout) {
			opsForValue.set("SHIRO_IS_LOCK"+username, "Lock");
			redisTemplate.expire("SHIRO_IS_LOCK"+username, locktimeout, TimeUnit.MINUTES);
		}
		
		//获取数据库中用户数据
		
		
		User user=userMapper.getByUserName(username);
		
		if(null==user) {
			throw new UnknownAccountException("用户不存在");
		}
		if(0==user.getStatus()) {
			throw new LockedAccountException("账户已被锁定,请联系管理员");
		}
		    

		//验证用户密码
		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassWord(), this.getName());
	      info.setCredentialsSalt(ByteSource.Util.bytes(user.getSalt()));
	   
	      // 获取所有session
          Collection<Session> sessions = sessionDAO.getActiveSessions();
          for (Session session: sessions) {
              User sysUser = (User)session.getAttribute("USER_SESSION");
              // 如果session里面有当前登陆的，则证明是重复登陆的，则将其剔除
              if( sysUser!=null ){
                  if( username.equals( sysUser.getUserName() ) ){
                      session.setTimeout(0);
                      logger.warn("被人挤下线");
                  }
              }
          }
	       
		return info;
	}
	
//    //授权
//	@Override
//	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//		// TODO Auto-generated method stub
//		 //获取所有用户principal
//		 String username= (String) principals.getPrimaryPrincipal();
//		 List<String> rlist=mdao.getrRoleByUserName(username);
//		Set<String> roles = new HashSet<>();
//		 for(int i=0;i<rlist.size();i++) {
//			 roles.add(rlist.get(i));
//		 }
//		 AuthorizationInfo info = new SimpleAuthorizationInfo(roles);
//		return info;
//	}

}
